
/****************************************************************************/

int kernelMultitaskerGetCurrentDirectory(char *buffer, int buffSize)
{
	// This function will fill the supplied buffer with the name of the
	// current working directory for the current process.  Returns 0 on 
	// success, negative otherwise.

	int status = 0;
	int lengthToCopy = 0;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);
  
	// Make sure the buffer we've been passed is not NULL
	if (buffer == NULL)
		return (status = ERR_NULLPARAMETER);

	ACQUIRE_LOCK_PROCESS_QUEUE();

	// Now, the number of characters we will copy is the lesser of 
	// buffSize or MAX_PATH_LENGTH
	lengthToCopy = min(buffSize, MAX_PATH_LENGTH);

	// Otay, copy the name of the current directory into the caller's buffer
	strncpy(buffer, (char *) kernelCurrentProcess->currentDirectory, lengthToCopy);

	RELEASE_LOCK_PROCESS_QUEUE();

	// Return success
	return (status = 0);
}

/****************************************************************************/

int kernelMultitaskerSetCurrentDirectory(const char *newDirName)
{
	// This function will change the current directory of the current
	// process.  Returns 0 on success, negative otherwise.

	int status = 0;
	kernelFileEntry *newDir = NULL;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);
  
	// Check params
	if (newDirName == NULL)
		return (status = ERR_NULLPARAMETER);

	// Call the appropriate filesystem function to find this supposed new 
	// directory.
	newDir = kernelFileLookup(newDirName);
	if (newDir == NULL)
		return (status = ERR_NOSUCHDIR);

	// Make sure the target is actually a directory
	if (newDir->type != dirT)
		return (status = ERR_NOTADIR);

	// Okay, copy the full name of the directory into the process
	kernelFileGetFullName(newDir, (char *) kernelCurrentProcess->currentDirectory);

	// Return success
	return (status = 0);
}

/****************************************************************************/

kernelTextInputStream *kernelMultitaskerGetTextInput(void)
{
	// This function will return the text input stream that is attached
	// to the current process

	// If multitasking hasn't yet been enabled, we can safely assume that
	// we're currently using the default console text input.
	if (!multitaskingEnabled)
		return (kernelTextGetCurrentInput());
	else
		// Ok, return the pointer
		return (kernelCurrentProcess->textInputStream);
}

/****************************************************************************/

int kernelMultitaskerSetTextInput(int processId, kernelTextInputStream *theStream)
{
	// Change the input stream of the process

	int status = 0;
	kernelProcess *theProcess = NULL;
	int count;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	// theStream is allowed to be NULL.

	ACQUIRE_LOCK_PROCESS_QUEUE();

	theProcess = getProcessById(processId);
	if (theProcess == NULL)
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	theProcess->textInputStream = theStream;

	if (theStream && (theProcess->type == proc_normal))
		theStream->ownerPid = theProcess->processId;

	// Do any child threads recursively as well.
	if (theProcess->descendentThreads)
	{
		for (count = 0; count < numQueued; count ++)
		{
			if ((processQueue[count]->parentProcessId == processId) &&
			    (processQueue[count]->type == proc_thread))
			{
				status = kernelMultitaskerSetTextInput(processQueue[count]->processId, theStream);
				if (status < 0)
				{
					RELEASE_LOCK_PROCESS_QUEUE();
					return (status);
				}
			}
		}
	}

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status = 0);
}

/****************************************************************************/

kernelTextOutputStream *kernelMultitaskerGetTextOutput(void)
{
	// This function will return the text output stream that is attached
	// to the current process

	// If multitasking hasn't yet been enabled, we can safely assume that
	// we're currently using the default console text output.
	if (!multitaskingEnabled)
		return (kernelTextGetCurrentOutput());
	else
		// Ok, return the pointer
		return (kernelCurrentProcess->textOutputStream);
}

/****************************************************************************/

int kernelMultitaskerSetTextOutput(int processId, kernelTextOutputStream *theStream)
{
	// Change the output stream of the process

	int status = 0;
	kernelProcess *theProcess = NULL;
	int count;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	// theStream is allowed to be NULL.

	ACQUIRE_LOCK_PROCESS_QUEUE();

	theProcess = getProcessById(processId);
	if (theProcess == NULL)
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	theProcess->textOutputStream = theStream;

	// Do any child threads recursively as well.
	if (theProcess->descendentThreads)
	{
		for (count = 0; count < numQueued; count ++)
		{
			if ((processQueue[count]->parentProcessId == processId) &&
			    (processQueue[count]->type == proc_thread))
			{
				status = kernelMultitaskerSetTextOutput(processQueue[count]->processId, theStream);
				if (status < 0)
				{
					RELEASE_LOCK_PROCESS_QUEUE();
					return (status);
				}
			}
		}
	}

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status = 0);
}

/****************************************************************************/

int kernelMultitaskerDuplicateIO(int firstPid, int secondPid, int clear)
{
	// Copy the input and output streams of the first process to the second
	// process.

	int status = 0;
	kernelProcess *firstProcess = NULL;
	kernelProcess *secondProcess = NULL;
	kernelTextInputStream *input = NULL;
	kernelTextOutputStream *output = NULL;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	ACQUIRE_LOCK_PROCESS_QUEUE();

	firstProcess  = getProcessById(firstPid);
	secondProcess = getProcessById(secondPid);

	if ((firstProcess == NULL) || (secondProcess == NULL))
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = ERR_NOSUCHPROCESS);
	}

	input  = firstProcess->textInputStream;
	output = firstProcess->textOutputStream;

	if (input)
	{
		secondProcess->textInputStream = input;
		input->ownerPid = secondPid;

		if (clear)
			kernelTextInputStreamRemoveAll(input);
	}

	if (output)
		secondProcess->textOutputStream = output;

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status = 0);
}

/****************************************************************************/

